home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / loading / ADotOutExtrasAccessImpl.c < prev    next >
C/C++ Source or Header  |  1990-10-03  |  33KB  |  1,136 lines

  1. /* begincopyright
  2.    Copyright (c) 1988-1990 Xerox Corporation. All rights reserved.
  3.    Use and copying of this software and preparation of derivative works based
  4.    upon this software are permitted. Any distribution of this software or
  5.    derivative works must comply with all applicable United States export
  6.    control laws. This software is made available AS IS, and Xerox Corporation
  7.    makes no warranty about the software, its performance or its conformity to
  8.    any specification. Any person obtaining a copy of this software is requested
  9.    to send their name and post office or electronic mail address to:
  10.    PCR Coordinator
  11.    Xerox PARC
  12.    3333 Coyote Hill Rd.
  13.    Palo Alto, CA 94304
  14.    endcopyright */
  15.  
  16. /*
  17.  * ADotOutExtrasAccessImpl.c
  18.  *
  19.  * Demers, October 2, 1990 9:12:12 am PDT
  20.  *
  21.  */
  22.  
  23. #include <xr/BasicTypes.h>
  24. #include <xr/Errno.h>
  25. #include <xr/ADotOutExtrasPvt.h>
  26.  
  27. #include <sys/file.h>
  28.  
  29. /*
  30.  * configuration limits
  31.  */
  32.  
  33. #define DEFAULT_EXTRA_SECTIONS    1
  34. #define MAX_EXTRA_SECTIONS    16
  35.  
  36.  
  37. /*
  38.  * error handling primitives
  39.  */
  40.  
  41. #define ResIsError(res) \
  42.     ((res) < 0)
  43.  
  44. #ifdef UNDEFINED
  45. #define ResFromErrno(errno) \
  46.     ( -(errno) )
  47. #else
  48. int ResFromErrno(e) int e; { return (-e); }
  49. #endif
  50.  
  51. #define ReturnIfErrorRes(res) \
  52.     if( ((int)(res)) < 0 ) return (res)
  53.  
  54. #define ReturnIfWrongRes(res,wanted,err) \
  55.     if( (res) != (wanted) ) \
  56.         return( ResIsError(res) ? res : ResFromErrno(err) )
  57.  
  58.  
  59. /*
  60.  * PCR extra subsec magic number
  61.  */
  62.  
  63. #define MAGIC_STRING "PCRExtraSection"
  64.  
  65. static int
  66. XR_aDotOutExtraMagic = 0;
  67.  
  68. int
  69. XR_SetADotOutExtraMagic(magic)
  70.     int magic;
  71. {
  72.     int ans = XR_aDotOutExtraMagic;
  73.     XR_aDotOutExtraMagic = magic;
  74.     return ans;
  75. }
  76.  
  77. int
  78. XR_GetADotOutExtraMagic()
  79. {
  80.     int ans;
  81.  
  82.     if( (ans = XR_aDotOutExtraMagic) == 0 ) {
  83.         (void)bcopy(MAGIC_STRING, ((char *)(&ans)), (sizeof ans));
  84.         XR_aDotOutExtraMagic = ans;
  85.     }
  86.     return ans;
  87. }
  88.  
  89.  
  90. /*
  91.  * internal I/O primitives
  92.  */
  93.  
  94. static int
  95. XR_AOXRead(lSeekProc, readProc, clientData, pos, buf, bytes)
  96.     XR_IOPositionProc lSeekProc;
  97.     XR_IOXferProc readProc;
  98.     XR_Pointer clientData;
  99.     int pos;
  100.     char *buf;
  101.     int bytes;
  102. {
  103.     int ans, nread;
  104.  
  105.     ans = (*lSeekProc)(pos, L_SET, clientData);
  106.     ReturnIfErrorRes(ans);
  107.     nread = 0;
  108.     for(;;) {
  109.         if( nread >= bytes ) return nread;
  110.         ans = (*readProc)(buf+nread, bytes-nread, clientData);
  111.         ReturnIfErrorRes(ans);
  112.         if( ans == 0 ) return nread;
  113.         nread += ans;
  114.     }
  115. }
  116.  
  117. static int
  118. XR_AOXWrite(lSeekProc, writeProc, clientData, pos, buf, bytes)
  119.     XR_IOPositionProc lSeekProc;
  120.     XR_IOXferProc writeProc;
  121.     XR_Pointer clientData;
  122.     int pos;
  123.     char *buf;
  124.     int bytes;
  125. {
  126.     int ans, nwritten;
  127.  
  128.     ans = (*lSeekProc)(pos, L_SET, clientData);
  129.     ReturnIfErrorRes(ans);
  130.     nwritten = 0;
  131.     for(;;) {
  132.         if( nwritten >= bytes ) return nwritten;
  133.         ans = (*writeProc)(buf+nwritten, bytes-nwritten, clientData);
  134.         ReturnIfErrorRes(ans);
  135.         if( ans == 0 ) return ResFromErrno(EIO);
  136.         nwritten += ans;
  137.     }
  138. }
  139.  
  140.  
  141. static int
  142. ShiftLeftInFile(lSeekProc, readProc, writeProc, clientData,
  143.         to, from, bytes)
  144.     XR_IOPositionProc lSeekProc;
  145.     XR_IOXferProc readProc;
  146.     XR_IOXferProc writeProc;
  147.     XR_Pointer clientData;
  148.     int to;
  149.     int from;
  150.     int bytes;
  151. {
  152.     int ans, nToMove;
  153.     char buf[2048];
  154.  
  155.     while( bytes > 0 ) {
  156.         if( (nToMove = (sizeof buf)) > bytes ) nToMove = bytes;
  157.         ans = XR_AOXRead(lSeekProc, readProc, clientData, from, buf, nToMove);
  158.         ReturnIfWrongRes(ans,nToMove,EFMT);
  159.         from += nToMove;
  160.         ans = XR_AOXWrite(lSeekProc, writeProc, clientData, to, buf, nToMove);
  161.         ReturnIfWrongRes(ans,nToMove,EIO);
  162.         to += nToMove;
  163.         bytes -= nToMove;
  164.     }
  165.     return 0;
  166. }
  167.  
  168.  
  169. static int
  170. ShiftRightInFile(lSeekProc, readProc, writeProc, clientData,
  171.         from, to, bytes)
  172.     XR_IOPositionProc lSeekProc;
  173.     XR_IOXferProc readProc;
  174.     XR_IOXferProc writeProc;
  175.     XR_Pointer clientData;
  176.     int from;
  177.     int to;
  178.     int bytes;
  179. {
  180.     int ans, nToMove;
  181.     char buf[2048];
  182.  
  183.     from += bytes;
  184.     to += bytes;
  185.     while( bytes > 0 ) {
  186.         if( (nToMove = (sizeof buf)) > bytes ) nToMove = bytes;
  187.         from -= bytes;
  188.         ans = XR_AOXRead(lSeekProc, readProc, clientData, from, buf, nToMove);
  189.         ReturnIfWrongRes(ans,nToMove,EFMT);
  190.         to -= bytes;
  191.         ans = XR_AOXWrite(lSeekProc, writeProc, clientData, to, buf, nToMove);
  192.         ReturnIfWrongRes(ans,nToMove,EIO);
  193.         bytes -= nToMove;
  194.     }
  195.     return 0;
  196. }
  197.  
  198.  
  199.  
  200. /*
  201.  * a.out header manipulation
  202.  */
  203.  
  204. static int
  205. XR_GetExec(lSeekProc, readProc, clientData, a)
  206.     XR_IOPositionProc lSeekProc;
  207.     XR_IOXferProc readProc;
  208.     XR_Pointer clientData;
  209.     struct exec *a;
  210. /*
  211.     Read the a.out header into *a.
  212.     Return 0 on success, (-errno) on failure.
  213. */
  214. {
  215.     int ans;
  216.  
  217.     ans = XR_AOXRead(lSeekProc, readProc, clientData,
  218.             /* pos=*/ 0, a, sizeof(*a));
  219.     ReturnIfWrongRes(ans,(sizeof(*a)),ENOEXEC);
  220.     if( N_BADMAG(*a) ) return( ResFromErrno(ENOEXEC) );
  221.     return 0;
  222. }
  223.  
  224.  
  225. /*
  226.  * struct extra_sections access
  227.  */
  228.  
  229. typedef struct ExtraSectionsRep {
  230.     struct /* a.out.h . */ extra_sections es_extra;
  231.     int es_sizes[MAX_EXTRA_SECTIONS];
  232. } * ExtraSections;
  233.  
  234. #define es_magic es_extra.extra_magic
  235. #define es_nsects es_extra.extra_nsects
  236.  
  237.  
  238. static int
  239. XR_FindExtraSections(lSeekProc, readProc, clientData, esPos)
  240.     XR_IOPositionProc lSeekProc;
  241.     XR_IOXferProc readProc;
  242.     XR_Pointer clientData;
  243.     int *esPos;
  244. /*
  245.     Store position of extra sections in *esPos.
  246.     Return 0 on success, (-errno) on failure.
  247. */
  248. {
  249.     int ans, fileOff, stringsBytes;
  250.     struct exec a;
  251.  
  252.     ans = XR_GetExec(lSeekProc, readProc, clientData, &a);
  253.     ReturnIfErrorRes(ans);
  254.     fileOff = N_STROFF(a);
  255.     ans = XR_AOXRead(lSeekProc, readProc, clientData,
  256.             fileOff, &stringsBytes, (sizeof stringsBytes));
  257.     ReturnIfWrongRes(ans, (sizeof stringsBytes), EFMT);
  258.     if( esPos != NIL ) *esPos = (fileOff + stringsBytes);
  259.     return 0;
  260. }
  261.  
  262.  
  263. static int
  264. XR_WriteExtraSections(lSeekProc, writeProc, clientData, esPos, es)
  265.     XR_IOPositionProc lSeekProc;
  266.     XR_IOXferProc writeProc;
  267.     XR_Pointer clientData;
  268.     int esPos;
  269.     ExtraSections es;
  270. /*
  271.     Write *es into file at specified position (length is self-described).
  272.     Return bytes written on success, (-errno) on failure.
  273. */
  274. {
  275.     int ans;
  276.     int esBytes;
  277.  
  278.     if( es == NIL ) return ResFromErrno(EFAULT);
  279.     if( es->es_nsects > MAX_EXTRA_SECTIONS ) return ResFromErrno(EBUG);
  280.     esBytes = (sizeof es->es_extra) + (es->es_nsects * sizeof(int));
  281.     ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
  282.             esPos, es, esBytes);
  283.     ReturnIfWrongRes(ans, esBytes, EIO);
  284.     return esBytes;
  285. }
  286.  
  287.  
  288.  
  289. static int
  290. XR_ReadExtraSections(lSeekProc, readProc, clientData,
  291.         esPos, es, esMaxBytes)
  292.     XR_IOPositionProc lSeekProc;
  293.     XR_IOXferProc readProc;
  294.     XR_Pointer clientData;
  295.     int esPos;
  296.     struct ExtraSectionsRep * es;
  297.     int esMaxBytes;
  298. /*
  299.     Get ExtraSections section from file at offset esPos,
  300.         store it in *es.
  301.     Return bytes read on success, (0 on end of file), (-errno) on failure.
  302. */
  303. {
  304.     int ans;
  305.     int bytes;
  306.     int maxSections;
  307.  
  308.     if( esMaxBytes < (sizeof es->es_extra) ) return ResFromErrno(EFAULT);
  309.     maxSections = (esMaxBytes - (sizeof es->es_extra)) / sizeof(int);
  310.     bytes = (sizeof es->es_extra);
  311.     ans = XR_AOXRead( lSeekProc, readProc, clientData,
  312.             esPos, es, bytes );
  313.     if( ans == 0 ) return 0;
  314.     ReturnIfWrongRes(ans, bytes, EFMT);
  315.     if( es->es_nsects > maxSections ) return ResFromErrno(EFMT);
  316.     bytes += (es->es_nsects * sizeof(int));
  317.     ans = XR_AOXRead( lSeekProc, readProc, clientData,
  318.             esPos, es, bytes );
  319.     ReturnIfWrongRes(ans, bytes, EFMT);
  320.     return bytes;
  321. }
  322.  
  323.  
  324. /*
  325.  * PCR subsection primitives
  326.  */
  327.  
  328. char *
  329. XR_GetEndOfGroupSubsecName()
  330. {
  331.     return "eog";
  332. }
  333.  
  334.  
  335. int
  336. XR_XSubsecHdr_GetHdrBytes(xssh)
  337.     XR_XSubsecHdr xssh;
  338. {
  339.     int nameBytes, ans;
  340.  
  341.     nameBytes = (1+strlen(xssh->xssh_name));
  342.     ans = XR_XSubsecHdr_sizeof(nameBytes);
  343.     if( (ans > (sizeof (*xssh)))
  344.             || (XR_XSubsecHdr_hdrBytes(xssh, nameBytes) != ans) )
  345.         return ResFromErrno(EFMT);
  346.     return ans;
  347. }
  348.  
  349.  
  350. int
  351. XR_XSubsecHdr_SetName(xssh, name)
  352.     XR_XSubsecHdr xssh;
  353.     char *name;
  354. {
  355.     int nameBytes, hdrLen;
  356.  
  357.     if( name == NIL ) name = "";
  358.     nameBytes = 1+strlen(name);
  359.     hdrLen = XR_XSubsecHdr_sizeof(nameBytes);
  360.     if( hdrLen > (sizeof (*xssh)) )
  361.         return ResFromErrno(ENAMETOOLONG);
  362.     (void)strcpy(xssh->xssh_name, name);
  363.     while( (nameBytes % sizeof(int)) != 0 ) {
  364.         xssh->xssh_name[nameBytes] = '\0';
  365.         nameBytes += 1;
  366.     }
  367.     XR_XSubsecHdr_hdrBytes(xssh, nameBytes) = hdrLen;
  368.     return hdrLen;
  369. }
  370.  
  371.  
  372. static int
  373. XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
  374.         xsshPos, xssh)
  375.     XR_IOPositionProc lSeekProc;
  376.     XR_IOXferProc readProc;
  377.     XR_Pointer clientData;
  378.     int xsshPos;
  379.     XR_XSubsecHdr xssh;
  380. {
  381.     int ans, xsshBytes;
  382.  
  383.     ans = XR_AOXRead(lSeekProc, readProc, clientData,
  384.             xsshPos, xssh, (sizeof(*xssh)) );
  385.     ReturnIfErrorRes(ans);
  386.     if( ans < XR_XSubsecHdr_sizeof(1) )
  387.         return ResFromErrno(EFMT);
  388.     xsshBytes = XR_XSubsecHdr_GetHdrBytes(xssh);
  389.     ReturnIfErrorRes(xsshBytes);
  390.     if( (ans < xsshBytes) )
  391.         return ResFromErrno(EFMT);
  392.     return xsshBytes;
  393. }
  394.  
  395. static int
  396. XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData, pos, xssh)
  397.     XR_IOPositionProc lSeekProc;
  398.     XR_IOXferProc readProc;
  399.     XR_Pointer clientData;
  400.     int pos;
  401.     XR_XSubsecHdr xssh;
  402. {
  403.     int ans;
  404.     int xsshBytes;
  405.  
  406.     if( pos < (sizeof xsshBytes) ) return ResFromErrno(EBUG);
  407.     ans = XR_AOXRead( lSeekProc, readProc, clientData,
  408.             pos-(sizeof xsshBytes), &xsshBytes, (sizeof xsshBytes) );
  409.     ReturnIfWrongRes(ans, (sizeof xsshBytes), EFMT);
  410.     if( pos < xsshBytes ) return ResFromErrno(EFMT);
  411.     return XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
  412.             pos-xsshBytes, xssh );
  413. }
  414.  
  415.  
  416. static int
  417. XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData, xsshPos, xssh)
  418.     XR_IOPositionProc lSeekProc;
  419.     XR_IOXferProc writeProc;
  420.     XR_Pointer clientData;
  421.     int xsshPos;
  422.     XR_XSubsecHdr xssh;
  423. {
  424.     int ans;
  425.     int bytes;
  426.  
  427.     bytes = XR_XSubsecHdr_GetHdrBytes(xssh);
  428.     ans = XR_AOXWrite(lSeekProc, writeProc, clientData, xsshPos, xssh, bytes);
  429.     ReturnIfWrongRes(ans, bytes, EIO);
  430.     return ans;
  431. }
  432.  
  433.  
  434. static int
  435. XR_WriteEndOfGroupSubsec(lSeekProc, writeProc, clientData,
  436.         xsshPos, xssh, groupBytes )
  437.     XR_IOPositionProc lSeekProc;
  438.     XR_IOXferProc writeProc;
  439.     XR_Pointer clientData;
  440.     int xsshPos;
  441.     XR_XSubsecHdr xssh;
  442.     int groupBytes;
  443. /*
  444.     Input value of groupbytes
  445.         <= 0 ==> abs value, doesn't count end-of-group subsec itself.
  446. */
  447. {
  448.     int ans;
  449.     int xsshBytes;
  450.     struct XR_XSubsecHdrRep xsshRep;
  451.  
  452.     if( xssh == NIL ) xssh = &xsshRep;
  453.     xssh->xssh_magic = XR_GetADotOutExtraMagic();
  454.     xsshBytes = XR_XSubsecHdr_SetName(xssh, XR_GetEndOfGroupSubsecName());
  455.     ReturnIfErrorRes(xsshBytes);
  456.     if( groupBytes <= 0 ) 
  457.         groupBytes = (-groupBytes) + xsshBytes + sizeof(int);
  458.     xssh->xssh_subsecBytes = groupBytes;
  459.     ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
  460.             xsshPos, xssh);
  461.     ReturnIfWrongRes(ans, xsshBytes, EIO);
  462.     ans = XR_AOXWrite( lSeekProc, writeProc, clientData,
  463.             xsshPos+xsshBytes, &(xssh->xssh_subsecBytes), sizeof(int) );
  464.     ReturnIfWrongRes(ans,sizeof(int),EIO);
  465.     return groupBytes;
  466. }
  467.  
  468.  
  469. static int
  470. XR_FindXSecInExtraSections(lSeekProc, readProc, clientData,
  471.         esPos, es, xsecIndex, xsecPos)
  472.     XR_IOPositionProc lSeekProc;
  473.     XR_IOXferProc readProc;
  474.     XR_Pointer clientData;
  475.     int esPos;
  476.     ExtraSections es;
  477.     int * xsecIndex;
  478.     int * xsecPos;
  479. /*
  480.     Find position of PCR extra section in supplied Extra Sections header.
  481.     Return 0 on success, (-errno) on error.
  482. */
  483. {
  484.     int ans;
  485.     unsigned fileOff;
  486.     int magic;
  487.     int i;
  488.     
  489.     fileOff = esPos + (sizeof es->es_extra) + (es->es_nsects * sizeof(int));;
  490.             /* skip extra sections header itself */
  491.     for( i = 0; i < es->es_nsects; i++ ) {
  492.         if( es->es_sizes[i] == 0 ) break;
  493.         ans = XR_AOXRead(lSeekProc, readProc, clientData,
  494.                 fileOff, &magic, (sizeof magic));
  495.         ReturnIfWrongRes(ans, (sizeof magic), EFMT);
  496.         if( magic == XR_GetADotOutExtraMagic() ) break;
  497.         fileOff += es->es_sizes[i];
  498.     }
  499.     if( xsecPos != NIL ) *xsecPos = fileOff;
  500.     if( xsecIndex != NIL ) *xsecIndex = i;
  501.     if( i >= es->es_nsects ) return ResFromErrno(ENOSPC);
  502.     /* TEMPORARY: index must be 0! */
  503.         if( i != 0 ) return ResFromErrno(ENOSPC);
  504.     return 0;
  505. }
  506.  
  507.  
  508. static int
  509. XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
  510.         xsecPos, xsecBytes)
  511.     XR_IOPositionProc lSeekProc;
  512.     XR_IOXferProc readProc;
  513.     XR_IOXferProc writeProc;
  514.     XR_Pointer clientData;
  515.     int *xsecPos;
  516.     int *xsecBytes;
  517. {
  518.     int ans;
  519.     int esPos;
  520.     int xsecIndex;
  521.     struct XR_XSubsecHdrRep xsshRep;
  522.     struct ExtraSectionsRep esRep;
  523.  
  524.     /* get extra sections */
  525.         ans = XR_FindExtraSections(lSeekProc, readProc, clientData, &esPos);
  526.         ReturnIfErrorRes(ans);
  527.  
  528.         ans = XR_ReadExtraSections(lSeekProc, readProc, clientData,
  529.                 esPos, &esRep, (sizeof esRep) );
  530.         ReturnIfErrorRes(ans);
  531.         if( ans == 0 ) {
  532.             if( writeProc == NIL ) return ResFromErrno(ENOSPC);
  533.             /* put empty extra sections header in esRep */
  534.             /* (it will be written below)        */
  535.                 esRep.es_magic = EXTRA_MAGIC;
  536.                 esRep.es_nsects = DEFAULT_EXTRA_SECTIONS;
  537.                 (void)bzero( esRep.es_sizes,
  538.                         esRep.es_nsects*sizeof(int) );
  539.         }
  540.  
  541.     /* get PCR extra section */
  542.         ans = XR_FindXSecInExtraSections(lSeekProc, readProc, clientData,
  543.                 esPos, &esRep, &xsecIndex, xsecPos);
  544.         ReturnIfErrorRes(ans);
  545.         if( xsecIndex >= esRep.es_nsects )
  546.             return ResFromErrno(ENOSPC);
  547.         if( ((xsecIndex+1) < esRep.es_nsects)
  548.                 && (esRep.es_sizes[(xsecIndex+1)] != 0) )
  549.             return ResFromErrno(ENOSPC);
  550.         (*xsecBytes) = esRep.es_sizes[xsecIndex];
  551.         if( (*xsecBytes) == 0 ) {
  552.             if( writeProc == NIL ) return ResFromErrno(ENOSPC);
  553.             ans = XR_WriteEndOfGroupSubsec(
  554.                     lSeekProc, writeProc, clientData,
  555.                     *xsecPos, &xsshRep, 0 );
  556.             ReturnIfErrorRes(ans);
  557.             (*xsecBytes) += RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
  558.             esRep.es_sizes[xsecIndex] = (*xsecBytes);
  559.             ans = XR_WriteExtraSections(lSeekProc, writeProc, clientData,
  560.                     esPos, &esRep);
  561.             ReturnIfErrorRes(ans);
  562.         }
  563.  
  564.     return 0;
  565. }
  566.  
  567.  
  568. static int
  569. XR_UpdateExtraSections(lSeekProc, readProc, writeProc, clientData, xsecLim)
  570.     XR_IOPositionProc lSeekProc;
  571.     XR_IOXferProc readProc;
  572.     XR_IOXferProc writeProc;
  573.     XR_Pointer clientData;
  574.     int xsecLim;
  575. {
  576.     int ans;
  577.     int esPos;
  578.     int xsecIndex;
  579.     int xsecPos;
  580.     int xsecBytes;
  581.     struct ExtraSectionsRep esRep;
  582.  
  583.     /* get extra sections */
  584.         ans = XR_FindExtraSections(lSeekProc, readProc, clientData, &esPos);
  585.         ReturnIfErrorRes(ans);
  586.  
  587.         ans = XR_ReadExtraSections(lSeekProc, readProc, clientData,
  588.                 esPos, &esRep, (sizeof esRep) );
  589.         ReturnIfErrorRes(ans);
  590.         if( ans == 0 ) return ResFromErrno(EBUG);
  591.  
  592.     /* get PCR extra section */
  593.         ans = XR_FindXSecInExtraSections(lSeekProc, readProc, clientData,
  594.                 esPos, &esRep, &xsecIndex, &xsecPos);
  595.         ReturnIfErrorRes(ans);
  596.         if( xsecIndex >= esRep.es_nsects )
  597.             return ResFromErrno(EBUG);
  598.         if( ((xsecIndex+1) < esRep.es_nsects)
  599.                 && (esRep.es_sizes[(xsecIndex+1)] != 0) )
  600.             return ResFromErrno(EBUG);
  601.         xsecBytes = esRep.es_sizes[xsecIndex];
  602.         if( xsecBytes == 0 )
  603.             return ResFromErrno(EBUG);
  604.  
  605.     /* update and write extra sections hdr */
  606.         esRep.es_sizes[xsecIndex] = RNDUPWORDSZ(xsecLim) - xsecPos;
  607.         ans = XR_WriteExtraSections(lSeekProc, writeProc, clientData,
  608.                 esPos, &esRep);
  609.         ReturnIfErrorRes(ans);
  610.  
  611.     return 0;
  612. }
  613.  
  614.  
  615.  
  616. /*
  617.  * EXPORTS
  618.  */
  619.  
  620.  
  621. int
  622. XR_EnumerateExtraSubsecs(lSeekProc, readProc, clientData,
  623.         subsecPos, callbackProc, callbackData)
  624.     XR_IOPositionProc lSeekProc;
  625.     XR_IOXferProc readProc;
  626.     XR_Pointer clientData;
  627.     int subsecPos;
  628.     XR_ExtraSubsecCallbackProc callbackProc;
  629.     XR_Pointer callbackData;
  630. {
  631.     int ans;
  632.     int xsecPos;
  633.     int xsecBytes;
  634.     int xsecLim;
  635.     int xsshPos;
  636.     int xsshBytes;
  637.     int groupBytes;
  638.     char *subsecName;
  639.     int subsecBytes;
  640.     struct XR_XSubsecHdrRep xsshRep;
  641.     
  642.  
  643.     ans = XR_GetXSec(lSeekProc, readProc, NIL, clientData,
  644.             &xsecPos, &xsecBytes);
  645.     if( ans == ResFromErrno(ENOSPC) ) return 0;
  646.     ReturnIfErrorRes(ans);
  647.     xsecLim = xsecPos + xsecBytes;
  648.  
  649.     if( subsecPos == 0 ) {
  650.         xsshPos = xsecPos;
  651.     } else if( subsecPos == (-1) ) {
  652.         /* read end-of-group subsec, use it to find beginning of last group */
  653.         ans = XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData,
  654.                 xsecLim-(sizeof groupBytes), &xsshRep);
  655.         ReturnIfErrorRes(ans);
  656.         if( strcmp(xsshRep.xssh_name, XR_GetEndOfGroupSubsecName()) != 0 )
  657.             return ResFromErrno(EFMT);
  658.         ans = XR_AOXRead(lSeekProc, readProc, clientData,
  659.                 xsecLim-(sizeof groupBytes), &groupBytes, (sizeof groupBytes) );
  660.         ReturnIfWrongRes(ans, (sizeof groupBytes), EFMT);
  661.         xsshPos = xsecLim - groupBytes;
  662.     } else {
  663.         ans = XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData,
  664.                 subsecPos, &xsshRep);
  665.         ReturnIfErrorRes(ans);
  666.         xsshPos = subsecPos - ans + RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
  667.     }
  668.     while( xsshPos < xsecLim ) {
  669.         ans = XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
  670.                 xsshPos, &xsshRep );
  671.         ReturnIfErrorRes(ans);
  672.         xsshBytes = ans;
  673.         subsecName = xsshRep.xssh_name;
  674.         subsecPos = xsshPos + xsshBytes;
  675.         subsecBytes = xsshRep.xssh_subsecBytes - xsshBytes;
  676.         ans = (*callbackProc)( subsecName, subsecPos,
  677.                     subsecBytes, callbackData );
  678.         ReturnIfWrongRes(ans, 0, 0);
  679.         xsshPos += RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
  680.     }
  681.     return 0;
  682. }
  683.  
  684.  
  685. /* Find implemented in terms of Enumerate */
  686.  
  687. typedef struct FindExtraSubsecCallbackDataRep {
  688.     char *fescd_subsecName;
  689.     int fescd_subsecPos;
  690.     int fescd_subsecBytes;
  691. } * FindExtraSubsecCallbackData;
  692.  
  693.  
  694. int
  695. MyExtraSubsecCallbackProc(subsecName, subsecPos, subsecBytes, fescd)
  696.     char * subsecName;
  697.     int subsecPos;
  698.     int subsecBytes;
  699.     FindExtraSubsecCallbackData fescd;
  700. {
  701.     if( strcmp(subsecName, fescd->fescd_subsecName) == 0 ) {
  702.         fescd->fescd_subsecPos = subsecPos;
  703.         fescd->fescd_subsecBytes = subsecBytes;
  704.         return 1;
  705.     }
  706.     return 0;
  707. }
  708.  
  709.  
  710.  
  711. int
  712. XR_FindExtraSubsec(lSeekProc, readProc, clientData,
  713.         subsecName, subsecPos, subsecBytes)
  714.     XR_IOPositionProc lSeekProc;
  715.     XR_IOXferProc readProc;
  716.     XR_Pointer clientData;
  717.     char * subsecName;
  718.     int * subsecPos;
  719.     int * subsecBytes;
  720. {
  721.     int ans;
  722.     int startPos = 0;
  723.     struct FindExtraSubsecCallbackDataRep fescdr;
  724.  
  725.     if( (subsecName == NIL) || (subsecName[0] == '\0') )
  726.         return ResFromErrno(EINVAL);;
  727.     if( subsecPos != NIL ) startPos = *subsecPos;
  728.  
  729.     fescdr.fescd_subsecName = subsecName;
  730.     fescdr.fescd_subsecPos = 0;
  731.     fescdr.fescd_subsecBytes = 0;
  732.     ans = XR_EnumerateExtraSubsecs(lSeekProc, readProc, clientData,
  733.         startPos, MyExtraSubsecCallbackProc, &fescdr);
  734.     if( subsecPos != NIL ) *subsecPos = fescdr.fescd_subsecPos;
  735.     if( subsecBytes != NIL ) *subsecBytes = fescdr.fescd_subsecBytes;
  736.     return ans;
  737. }
  738.  
  739.  
  740. /* Delete implemented in terms of Enumerate */
  741.  
  742. typedef struct DeleteCopierDataRep {
  743.     int dcd_entryCnt;
  744.     XR_IOPositionProc dcd_lSeekProc;
  745.     XR_IOXferProc dcd_readProc;
  746.     XR_IOXferProc dcd_writeProc;
  747.     XR_Pointer dcd_clientData;
  748.     XR_ExtraSubsecCallbackProc dcd_underDallbackProc;
  749.     XR_Pointer dcd_underCallbackData;
  750.     int dcd_toPos;
  751. } * DeleteCopierData;
  752.  
  753.  
  754. static int
  755. DeleteCopier(subsecName, subsecPos, subsecBytes, dcd)
  756.     char * subsecName;
  757.     int subsecPos;
  758.     int subsecBytes;
  759.     DeleteCopierData dcd;
  760. {
  761.     int ans;
  762.     bool deleteMe;
  763.     int fromPos;
  764.     int fromBytes;
  765.     struct XR_XSubsecHdrRep xsshRep;
  766.  
  767.     dcd->dcd_entryCnt += 1;
  768.     ans = XR_GetXSubsecHdrFromClientPos( dcd->dcd_lSeekProc,
  769.             dcd->dcd_readProc, dcd->dcd_clientData,
  770.             subsecPos, &xsshRep );
  771.     ReturnIfErrorRes(ans);
  772.     if( dcd->dcd_entryCnt == 1 ) dcd->dcd_toPos = (subsecPos - ans);
  773.     fromPos = subsecPos - ans;
  774.     fromBytes = xsshRep.xssh_subsecBytes;
  775.  
  776.     ans = (*(dcd->dcd_underDallbackProc))(subsecName, subsecPos, subsecBytes,
  777.             dcd->dcd_underCallbackData);
  778.     ReturnIfErrorRes(ans);
  779.     if( ans == 0 ) /* subsec must be preserved */ {
  780.         if( dcd->dcd_toPos != fromPos ) {
  781.             ans = ShiftLeftInFile(
  782.                     dcd->dcd_lSeekProc, dcd->dcd_readProc,
  783.                     dcd->dcd_writeProc, dcd->dcd_clientData,
  784.                     dcd->dcd_toPos, fromPos, fromBytes);
  785.             ReturnIfErrorRes(ans);
  786.         }
  787.         dcd->dcd_toPos += RNDUPWORDSZ(fromBytes);
  788.     }
  789.  
  790.     return 0;
  791. }
  792.  
  793.  
  794. int
  795. XR_DeleteExtraSubsecs(lSeekProc, readProc, writeProc, fTruncateProc, clientData,
  796.         subsecPos, callbackProc, callbackData)
  797.     XR_IOPositionProc lSeekProc;
  798.     XR_IOXferProc readProc;
  799.     XR_IOXferProc writeProc;
  800.     XR_IOPositionProc fTruncateProc;
  801.     XR_Pointer clientData;
  802.     int subsecPos;
  803.     XR_ExtraSubsecCallbackProc callbackProc;
  804.     XR_Pointer callbackData;
  805. {
  806.     int ans;
  807.     int esPos;
  808.     int xsecIndex;
  809.     struct ExtraSectionsRep esRep;
  810.     struct DeleteCopierDataRep dcdRep;
  811.  
  812.     /* enumerate subsecs, copying those to be preserved */
  813.         dcdRep.dcd_entryCnt = 0;
  814.         dcdRep.dcd_lSeekProc = lSeekProc;
  815.         dcdRep.dcd_readProc = readProc;
  816.         dcdRep.dcd_writeProc = writeProc;
  817.         dcdRep.dcd_clientData = clientData;
  818.         dcdRep.dcd_underDallbackProc = callbackProc;
  819.         dcdRep.dcd_underCallbackData = callbackData;
  820.         dcdRep.dcd_toPos = (-1);
  821.         ans = XR_EnumerateExtraSubsecs(lSeekProc, readProc, clientData,
  822.                 subsecPos, DeleteCopier, &dcdRep);
  823.         ReturnIfErrorRes(ans);
  824.  
  825.     if( dcdRep.dcd_entryCnt == 0 ) /* there was nothing to delete */ {
  826.         return 0;
  827.     }
  828.  
  829.     /* truncate file to its new length */
  830.         if( fTruncateProc != NIL ) {
  831.             ans = (*fTruncateProc)(dcdRep.dcd_toPos, L_SET, clientData);
  832.             ReturnIfErrorRes(ans);
  833.         }
  834.  
  835.     /* update extra sections header */
  836.         ans = XR_UpdateExtraSections(
  837.                 lSeekProc, readProc, writeProc, clientData,
  838.                 dcdRep.dcd_toPos );
  839.         ReturnIfErrorRes(ans);
  840.  
  841.     return 0;
  842. }
  843.  
  844.  
  845. /* Add subsec group */
  846.  
  847. int
  848. XR_AddSubsecGroup(lSeekProc, readProc, writeProc, clientData)
  849.     XR_IOPositionProc lSeekProc;
  850.     XR_IOXferProc readProc;
  851.     XR_IOXferProc writeProc;
  852.     XR_Pointer clientData;
  853. {
  854.     int ans;
  855.     int xsecPos;
  856.     int xsecBytes;
  857.     int xsshPos;
  858.     int xsshBytes;
  859.     int clientPos;
  860.     struct XR_XSubsecHdrRep xsshRep;
  861.  
  862.     /* get extra sections */
  863.         ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
  864.                 &xsecPos, &xsecBytes );
  865.         ReturnIfErrorRes(ans);
  866.  
  867.     /* write new end of group subsec */
  868.         xsshPos = xsecPos + xsecBytes;
  869.         xsshRep.xssh_magic = XR_GetADotOutExtraMagic();
  870.         xsshBytes = XR_XSubsecHdr_SetName(&xsshRep,
  871.                 XR_GetEndOfGroupSubsecName());
  872.         ReturnIfErrorRes(xsshBytes);
  873.         xsshRep.xssh_subsecBytes = xsshBytes + sizeof(int);
  874.         ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
  875.                 xsshPos, &xsshRep);
  876.         ReturnIfErrorRes(ans);
  877.         clientPos = xsshPos + xsshBytes;
  878.         ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
  879.                 clientPos, &(xsshRep.xssh_subsecBytes), sizeof(int));
  880.         ReturnIfWrongRes(ans,sizeof(int),EIO);
  881.  
  882.     /* update and write extra sections hdr */
  883.         ans = XR_UpdateExtraSections(
  884.                 lSeekProc, readProc, writeProc, clientData,
  885.                 xsshPos + xsshRep.xssh_subsecBytes );
  886.         ReturnIfErrorRes(ans);
  887.  
  888.     return clientPos;
  889. }
  890.  
  891.  
  892.  
  893. int
  894. XR_InsertExtraSubsec(lSeekProc, readProc, writeProc, clientData,
  895.         subsecName, subsecBytes, subsecPos)
  896.     XR_IOPositionProc lSeekProc;
  897.     XR_IOXferProc readProc;
  898.     XR_IOXferProc writeProc;
  899.     XR_Pointer clientData;
  900.     char * subsecName;
  901.     int subsecBytes;
  902.     int * subsecPos;
  903. {
  904.     int ans;
  905.     bool appending;
  906.     int xsecPos;
  907.     int xsecBytes;
  908.     int xsshPos, xsshPosNew;
  909.     int xsshBytes, xsshBytesNew;
  910.     int suffixBytes;
  911.     int groupBytes;
  912.     int groupBytesPos;
  913.     int clientPos;
  914.     struct XR_XSubsecHdrRep xsshRep, xsshRepNew;
  915.  
  916.     appending = ( (subsecPos == NIL) || ((*subsecPos) < 0) );
  917.  
  918.     ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
  919.             &xsecPos, &xsecBytes);
  920.     ReturnIfErrorRes(ans);
  921.  
  922.     /* find position to insert new subsec */
  923.         clientPos = ((appending)
  924.                 ? (xsecPos + xsecBytes - sizeof(int))
  925.                 : (*subsecPos) );
  926.         ans = XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData,
  927.                 clientPos, &xsshRep );
  928.         ReturnIfErrorRes(ans);
  929.         xsshPosNew = xsshPos = (clientPos - ans);
  930.  
  931.     /* construct new header */
  932.         xsshRepNew.xssh_magic = XR_GetADotOutExtraMagic();
  933.         xsshBytesNew = XR_XSubsecHdr_SetName(&xsshRepNew, subsecName);
  934.         ReturnIfErrorRes(xsshBytesNew);
  935.         xsshRepNew.xssh_subsecBytes = subsecBytes + xsshBytesNew;
  936.         suffixBytes = (xsecPos + xsecBytes) - xsshPosNew;
  937.  
  938.     /* find matching end-of-group section and update its length */
  939.         for(;;) {
  940.             if( strcmp(xsshRep.xssh_name, XR_GetEndOfGroupSubsecName()) == 0 )
  941.                 break;
  942.             xsshPos += RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
  943.             ans = XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
  944.                     xsshPos, &xsshRep );
  945.             ReturnIfErrorRes(ans);
  946.         }
  947.         groupBytesPos = xsshPos + xsshRep.xssh_subsecBytes
  948.                 - (sizeof groupBytes);
  949.         ans = XR_AOXRead(lSeekProc, readProc, clientData,
  950.                 groupBytesPos, &groupBytes, (sizeof groupBytes));
  951.         ReturnIfWrongRes(ans, (sizeof groupBytes), EFMT);
  952.         groupBytes += RNDUPWORDSZ(xsshRepNew.xssh_subsecBytes);
  953.         ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
  954.                 groupBytesPos, &groupBytes, (sizeof groupBytes));
  955.         ReturnIfWrongRes(ans, (sizeof groupBytes), EIO);
  956.  
  957.     /* update and rewrite extra sections header */
  958.         ans = XR_UpdateExtraSections(
  959.                 lSeekProc, readProc, writeProc, clientData,
  960.                 xsecPos + groupBytes ); 
  961.         ReturnIfErrorRes(ans);
  962.  
  963.     /* shift file suffix right */
  964.         ans = ShiftRightInFile(
  965.                 lSeekProc, readProc, writeProc, clientData,
  966.                 xsshPosNew,
  967.                 xsshPosNew+RNDUPWORDSZ(xsshRepNew.xssh_subsecBytes),
  968.                 suffixBytes );
  969.         ReturnIfErrorRes(ans);
  970.                 
  971.     /* write new header */
  972.         ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
  973.                 xsshPosNew, &xsshRepNew );
  974.         ReturnIfErrorRes(ans);
  975.  
  976.     if( subsecPos != NIL ) *subsecPos = xsshPosNew + xsshBytesNew;
  977.  
  978.     return 0;
  979. }
  980.  
  981.  
  982.  
  983.  
  984. int
  985. XR_StartAddExtraSubsec(lSeekProc, readProc, writeProc, clientData,
  986.         subsecName, subsecPos)
  987.     XR_IOPositionProc lSeekProc;
  988.     XR_IOXferProc readProc;
  989.     XR_IOXferProc writeProc;
  990.     XR_Pointer clientData;
  991.     char * subsecName;
  992.     int * subsecPos;
  993. {
  994.     int ans;
  995.     int xsecPos;
  996.     int xsecBytes;
  997.     int xsshPos;
  998.     int xsshBytes;
  999.     int clientPos;
  1000.     int savedGroupBytes;
  1001.     struct XR_XSubsecHdrRep xsshRep;
  1002.  
  1003.     if( (subsecName == NIL) || (subsecName[0] == '\0') )
  1004.         return ResFromErrno(EINVAL);
  1005.  
  1006.     ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
  1007.             &xsecPos, &xsecBytes);
  1008.     ReturnIfErrorRes(ans);
  1009.  
  1010.     /* position to beginning of new subsec */
  1011.         clientPos = xsecPos + xsecBytes - (sizeof savedGroupBytes);
  1012.         ans = XR_AOXRead(lSeekProc, readProc, clientData,
  1013.                 clientPos, &savedGroupBytes, (sizeof savedGroupBytes) );
  1014.         ReturnIfWrongRes(ans, (sizeof savedGroupBytes), EFMT);
  1015.         ans = XR_GetXSubsecHdrFromClientPos(
  1016.                 lSeekProc, readProc, clientData, 
  1017.                 clientPos, &xsshRep );
  1018.         ReturnIfErrorRes(ans);
  1019.         xsshBytes = ans;
  1020.         if( strcmp(xsshRep.xssh_name, XR_GetEndOfGroupSubsecName()) != 0 )
  1021.             return ResFromErrno(EFMT);
  1022.         xsshPos = clientPos - xsshBytes;
  1023.  
  1024.     /* write new subsec hdr */
  1025.         xsshRep.xssh_magic = XR_GetADotOutExtraMagic();
  1026.         xsshBytes = XR_XSubsecHdr_SetName(&xsshRep, subsecName);
  1027.         ReturnIfErrorRes(xsshBytes);
  1028.         xsshRep.xssh_subsecBytes = savedGroupBytes; /* until commit */
  1029.         ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
  1030.                 xsshPos, &xsshRep);
  1031.         ReturnIfErrorRes(ans);
  1032.  
  1033.     /* update and write extra sections hdr */
  1034.         ans = XR_UpdateExtraSections(
  1035.                 lSeekProc, readProc, writeProc, clientData,
  1036.                 xsshPos );
  1037.         ReturnIfErrorRes(ans);
  1038.  
  1039.     if( subsecPos != NIL ) *subsecPos = xsshPos + xsshBytes;
  1040.     return 0;
  1041. }
  1042.  
  1043.  
  1044.  
  1045. int
  1046. XR_FinishAddExtraSubsec(lSeekProc, readProc, writeProc, clientData,
  1047.         subsecBytes) 
  1048.     XR_IOPositionProc lSeekProc;
  1049.     XR_IOXferProc readProc;
  1050.     XR_IOXferProc writeProc;
  1051.     XR_Pointer clientData;
  1052.     int subsecBytes;
  1053. {
  1054.     int ans;
  1055.     int xsecPos;
  1056.     int xsecBytes;
  1057.     int xsshPos;
  1058.     int xsshBytes;
  1059.     int clientPos;
  1060.     int groupBytes;
  1061.     int roundedSubsecBytes;
  1062.     struct XR_XSubsecHdrRep xsshRep;
  1063.  
  1064.     ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
  1065.             &xsecPos, &xsecBytes);
  1066.     ReturnIfErrorRes(ans);
  1067.  
  1068.     /* retrieve groupBytes */
  1069.         xsshPos = xsecPos + xsecBytes;
  1070.         xsshBytes = XR_ReadXSubsecHdr( lSeekProc, readProc, clientData, 
  1071.                 xsshPos, &xsshRep );
  1072.         ReturnIfErrorRes(xsshBytes);
  1073.         groupBytes = xsshRep.xssh_subsecBytes;
  1074.  
  1075.     /* update and rewrite subsec hdr, update groupbytes */
  1076.         if( subsecBytes >= 0 ) {
  1077.             xsshRep.xssh_subsecBytes = xsshBytes + subsecBytes;
  1078.             roundedSubsecBytes = RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
  1079.             groupBytes += roundedSubsecBytes;
  1080.             ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
  1081.                     xsshPos, &xsshRep);
  1082.             ReturnIfErrorRes(ans);
  1083.             xsshPos += roundedSubsecBytes;
  1084.         }
  1085.  
  1086.     /* append end-of-group subsec */
  1087.         ans = XR_XSubsecHdr_SetName( &xsshRep,
  1088.                 XR_GetEndOfGroupSubsecName() );
  1089.         ReturnIfErrorRes(ans);
  1090.         xsshBytes = ans;
  1091.         xsshRep.xssh_subsecBytes = xsshBytes + (sizeof groupBytes);
  1092.         roundedSubsecBytes = RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
  1093.         ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
  1094.                 xsshPos, &xsshRep );
  1095.         ReturnIfWrongRes(ans, xsshBytes, EIO);
  1096.         ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
  1097.                 xsshPos+xsshBytes, &groupBytes, (sizeof groupBytes) );
  1098.         ReturnIfWrongRes(ans, (sizeof groupBytes), EIO);
  1099.         xsshPos += roundedSubsecBytes;
  1100.  
  1101.     /* update and write extra sections hdr */
  1102.         ans = XR_UpdateExtraSections(
  1103.                 lSeekProc, readProc, writeProc, clientData,
  1104.                 xsshPos );
  1105.         ReturnIfErrorRes(ans);
  1106.         
  1107.     return 0;
  1108. }
  1109.  
  1110.  
  1111. int
  1112. XR_DeleteAllExtraSubsecs(lSeekProc, readProc, writeProc, fTruncateProc,
  1113.         clientData)
  1114.     XR_IOPositionProc lSeekProc;
  1115.     XR_IOXferProc readProc;
  1116.     XR_IOXferProc writeProc;
  1117.     XR_IOPositionProc fTruncateProc;
  1118.     XR_Pointer clientData;
  1119. {
  1120.     int ans;
  1121.     int xsecPos;
  1122.     int xsecBytes;
  1123.  
  1124.     ans = XR_GetXSec(lSeekProc, readProc, NIL, clientData,
  1125.             &xsecPos, &xsecBytes);
  1126.     ReturnIfErrorRes(ans);
  1127.     ans = XR_UpdateExtraSections(
  1128.             lSeekProc, readProc, writeProc, clientData,
  1129.             xsecPos );
  1130.     ReturnIfErrorRes(ans);
  1131.     ans = (*fTruncateProc)(xsecPos, L_SET, clientData);
  1132.     ReturnIfErrorRes(ans);
  1133.     return 0;
  1134. }
  1135.  
  1136.